#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <cmath>
#include "wumanber.h"

using namespace std;
using namespace urltagminning;

float url_weight = 1.0;
float title_weight = 3.0;
float content_weight = 2.0;

// trim from start
static inline void ltrim(std::string &s)
{
	s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
}

// trim from end
static inline void rtrim(std::string &s)
{
	s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}

// trim from both ends
static inline void  trim( std::string &s)
{
	rtrim(s);
    ltrim(s);
}


void split(const std::string& instr, std::vector<std::string>& result, const std::string& delim)
{
    std::string str(instr);
    size_t pos;
    while ((pos = str.find_first_of(delim)) != str.npos)
    {
        if (pos > 0)
            result.push_back(str.substr(0, pos));
        str = str.substr(pos + 1);
    }
    if (str.length() > 0)
        result.push_back(str);
}

int toint(const std::string& str){return atoi(str.c_str());}
float tof(const std::string& str){return atof(str.c_str());}
float log2(long unsigned int n)
{
	n++;
	if (n < 0)
		n = 1;
	return log(n)/log(2);
}

//urlpvuvtitlecontent
int  extract(string& str, map<string, float>& feature)
{
	int ret = 0;
	vector<string> v;
	split(str, v, "\005");
	if (v.size() >= 4 && v[0].length() != 0)
	{
		string url = v[0];
		string pv =	v[1];
		string uv = v[2];
		string title = v[3];
		string content = "EMPTY";
		if (v.size() == 5)
			content = v[4];
		
		str = url + "\t" + pv + "\t" + uv + "\t" + title + "\t" + content;
//		if (v[0] == "http://baike.baidu.com/view/33740.htm")
//			ret = 1;
		feature.insert(make_pair<string ,float>(url, url_weight));//url
		feature.insert(make_pair<string ,float>(pv, 0));//pv
		feature.insert(make_pair<string ,float>(uv, 0));//uv
		feature.insert(make_pair<string ,float>(title, title_weight));//title
		feature.insert(make_pair<string ,float>(content, content_weight));//content
	}
	return ret;
}

int main(int argc, char* argv[])
{
	if (argc != 5)
	{
		cout << "Usage: ./matcher patterns context_weight inputurls base_threshold" << endl;
		cout << "\ta). patterns's format:pattern<TAB>weight" << endl;
        cout << "\ta). context_weight's format:url_weight<TAB>title_weight<TAB>content_weight" << endl;
		cout << "\tb). inputurls's format: url<^A>pv<^A>uv<^A>title<^A>content" << endl;
		cout << "\tc). threashold default is 0.8" << endl;
		cout << "\td). output will print to screen." << endl;
		cout << "\te). how to postprocess the output: | sort -k1 -nr > type.urls" << endl;
		return -1;
	}

    string line;
    WuManber wu;
    string pattern_weight_file = argv[1];
    string context_weight_file = argv[2];
    string url_file = argv[3];
	float base_threshold = tof(argv[4]);

    // step 1: read pattern_weight_file
	ifstream patwet(pattern_weight_file.c_str());
	map<string, float> weightpattern;
	while(getline(patwet, line))
	{
		vector<string> keyword_weight_vec;
		split(line, keyword_weight_vec, "\t");
		if (keyword_weight_vec.size() != 2)
			continue;
		weightpattern[keyword_weight_vec[0]] = tof(keyword_weight_vec[1]);
	}

    // setp 2: init wumanber
	wu.Init(weightpattern);
	patwet.close();

    // setp 3 initial url title and content weight
    vector<string> weight_vec;
    ifstream context_weight(context_weight_file.c_str());
	while(getline(context_weight, line))
	{
		split(line, weight_vec, "\t");
        if (weight_vec.size() == 3)
		{
            url_weight = tof(weight_vec[0]);
            title_weight = tof(weight_vec[1]);
            content_weight = tof(weight_vec[2]);
            break;
        }
	}

    //step4: mark using wumanber in paraell
    ifstream text(url_file.c_str());
    while (getline(text, line))
    {
		map<string, float> feature;
		trim(line);
		extract(line, feature);
		float score = 0;
		map<string, float>::iterator biter = feature.begin();
		map<string, float>::iterator eiter = feature.end();
		for (; biter != eiter; ++ biter)
		{
			ResultSetType  res;
			float sr = wu.WeightedSearch(biter->first, res);
			score += sr * biter->second * (res.size()+1) / ((biter->first).length()+1);
//			for (ResultSetType::iterator iter = res.begin(); iter != res.end(); ++iter)
//				cerr << "keyword: " << iter->first << ", score: " << iter->second << endl;
//			cerr << "text: " << biter->first << endl;
//			cerr << "score: " << sr << endl;
//			cerr << "text weight: " << biter->second << endl;
//			cerr << "keyword num: " << res.size() + 1 <<endl;
//			cerr << "content length: " << (biter->first).length()+1 << endl;
//			cerr << endl << endl;
			
		}
		if (score >= base_threshold)
			cout << score << "\t" << line << endl;
    }

    return 0;
}
